//
//  optimization.h
//  template4
//
//  Created by Yuchen Liu on 6/5/12.
//  Copyright 2012 UCLA. All rights reserved.
//

#ifndef template4_optimization_h
#define template4_optimization_h



#endif

#include "common.h"
#include "engine.h"

struct ParamSet 
{
    int numController;
    int numTimepoints;
    double** u; // first order: timepoint, second order: controller param
    
    ParamSet()
    {
        numController = numTimepoints = 0;
        u = NULL;
    }
    
    ParamSet(const ParamSet *param)
    {
        numController = param->numController;
        numTimepoints = param->numTimepoints;
        
        u = new double* [numTimepoints];
        for (int i = 0; i < numTimepoints; ++i)
        {
            u[i] = new double [numController];
            memcpy(u[i], param->u[i], sizeof(double)*numController);
        }
    }
    
    ParamSet(const char *filename)
    {
        FILE *inf = fopen(filename, "r");
        
        fscanf(inf, "%d", &numTimepoints);
        fscanf(inf, "%d", &numController);
        
        u = new double* [numTimepoints];
        for (int i = 0; i < numTimepoints; ++i)
        {
            u[i] = new double [numController];
            for (int j = 0; j < numController; ++j)
                fscanf(inf, "%lf", &(u[i][j]));
        }
        fclose(inf);
    }
    
    ~ParamSet()
    {
        for (int i = 0; i < numTimepoints; ++i)
            delete [] u[i];
        delete [] u;
    }
    
    void output(const char *filename)
    {
//        freopen (filename, "w", stdout);

        printf("%d %d\n", numTimepoints, numController);
        for (int i = 0; i < numTimepoints; ++i)
        {
            printf("%lf", u[i][0]);
            for (int j = 1; j < numController; ++j)
                printf(" %lf", u[i][j]);
            printf("\n");
        }
        fclose(stdout);
    }
};


class COptimization
{
private: 
    int numController;
    double duration;
    double timestep;
    int numTimepoints;
    
    double* ctrUpper;
    double* ctrLower;
    
public:
    COptimization();
    ParamSet* initialize(int _numController, double _duration, double _timestep, 
                        const double* _ctrUpper, const double* _ctrLower, const double* _initVal);
    void update(ParamSet *curParam, double heat, double range);
    
    bird_dof* realize_bird_action(ParamSet param);
    double evaluate_objective_function(bird_status* series, const ParamSet *paramSet);
    
    inline int getNumTimepoints()
    {
        return numTimepoints;
    }
    
    
};